<?php
/**
 * @version		3.01 $Id: k2autofbook.php 12 2012-05-29 05:54:04Z webbochsant@gmail.com $
 * @package		AutoFBook K2 Plugin (K2 plugin)
 * @author    Daniel Eliasson Stilero AB - http://www.stilero.com
 * @copyright	Copyright (c) 2011 Stilero AB. All rights reserved.
 * 	@license	GPLv2
* 	Joomla! is free software. This version may have been modified pursuant
* 	to the GNU General Public License, and as distributed it includes or
* 	is derivative of works licensed under the GNU General Public License or
* 	other free or open source software licenses.
 * 
 *  This file is part of AutoFBook K2 Plugin.

    AutoFBook K2 Plugin is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AutoFBook K2 Plugin is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with AutoFBook K2 Plugin.  If not, see <http://www.gnu.org/licenses/>.
*/

// no direct access
defined('_JEXEC') or die ('Restricted access');

jimport('joomla.plugin.plugin');

// Load the K2 Plugin API
//JLoader::register('K2Plugin', JPATH_ADMINISTRATOR.DS.'components'.DS.'com_k2'.DS.'lib'.DS.'k2plugin.php');
JLoader::register('K2HelperRoute', JPATH_SITE.DS.'components'.DS.'com_k2'.DS.'helpers'.DS.'route.php');

// Initiate class to hold plugin events
class plgSystemK2autofbook extends JPlugin {
    var $config;
    var $inBackend;
    var $error = false;
    var $CheckClass;
    var $fbAppID;
    var $fbAppSecret;
    var $fbOauthAccessToken;
    var $fbOauthCode;
    const HTTP_STATUS_OK = '200';
    const ERROR_RETURNURL_NOT_SPECIFIED = '10';
    const ERROR_AUTHTOKENURL_NOT_SPECIFIED = '11';
    const ERROR_URL_NOT_VALID = '12';
    const ERROR_POST_FAIL = '13';
    const ERROR_COMMUNICATION_FAULT = '14';
    const ERROR_OAUTH_EXCEPTION = '50';
    const ERROR_OAUTH_OTHER = '55';

    //Facebook parameters
    var $access_token_url = "https://www.facebook.com/dialog/oauth"; 
    var $authorization_scope = "scope=publish_stream,share_item,offline_access,manage_pages";
    var $authorization_response_type = "response_type=token";
    var $ogTagsAdded = false;
    
    function plgSystemK2autofbook( &$subject, $config) {
        parent::__construct($subject, $config);
        $language = JFactory::getLanguage();
        $language->load('plg_system_k2autofbook', JPATH_ADMINISTRATOR, 'en-GB', true);
        $language->load('plg_system_k2autofbook', JPATH_ADMINISTRATOR, null, true);
        $this->fbAppID = $this->params->def('fb_app_id');
        $this->fbAppSecret = $this->params->def('fb_app_secret');
        $this->fbOauthAccessToken = $this->params->def('auth_token');
        $this->fbOauthCode = $this->params->def('auth_code');
        $this->config = array(
            'shareLogTableName'     =>      '#__k2autofbook_posted',
            'pluginLangPrefix'      =>      'PLG_K2_AUTOFBOOK_',
            'extType'               =>      'k2',
            'pluginElement'         =>      'k2autofbook',
            'classFolder'           =>      'k2autofbookclasses',
            'articleClass'          =>      'Article',
            'articleClassFile'      =>      'article.php',
            'fbookClass'            =>      'FBookClass',
            'fbookClassFile'        =>      'fbookClass.php',
            'jfbClass'              =>      'JFBClass',
            'jfbClassFile'          =>      'jfbClass.php',
            'shareControllerClass'  =>      'stlShareControllerClass',
            'shareControllerFile'   =>      'stlShareControllerClass.php',
            'fbControllerClass'     =>      'fbControllerClass',
            'fbControllerFile'      =>      'fbControllerClass.php',
            'fbPageID'              =>      $this->params->def('fb_page_id'),
            'categoriesToShare'     =>      $this->params->def('section_id'),
            'shareDelay'            =>      $this->params->def('delay'),
            'articlesNewerThan'     =>      $this->params->def('items_newer_than'),
            'addOGTags'             =>      $this->params->def('add_ogtags')
        ); 
    }

    public function onAfterK2Save(&$article, $isNew){
        $this->inBackend = true;
        $this->setupClasses();
        $ArticleObj = new $this->config['articleClass']($article, 'k2');
        $this->CheckClass->setArticleObject($ArticleObj);
        $this->postArticleToFB();
        return;
    }
    
    public function onK2AfterDisplayContent( & $article, & $params, $limitstart) {
        $this->inBackend = false;
        $this->setupClasses();
        $ArticleObj = new $this->config['articleClass']($article, 'k2');
        $this->CheckClass->setArticleObject($ArticleObj);
        $this->postArticleToFB();
        return;
    }
    
    function onPrepareContent(  &$article, &$params, $limitstart=0 ) {
        $this->setupClasses();
        $ArticleObj = new $this->config['articleClass']($article, 'k2');
        $this->CheckClass->setArticleObject($ArticleObj);
        $this->insertOGTags($ArticleObj);
        return;
    }
    
    function onContentPrepare(  $article, &$params, $limitstart=0 ) {
        $this->setupClasses();
        $ArticleObj = new $this->config['articleClass']($article, 'k2');
        $this->CheckClass->setArticleObject($ArticleObj);
        $this->insertOGTags($ArticleObj);
        return;
    }
    
    function onAfterDispatch( ){
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        $actualSignature = JRequest::getVar('signature');
        $code = JRequest::getVar('code');
        if( ($code == '') || ($actualSignature == '') ){
            return;
        }
        if(!is_object($this->CheckClass)){
                $this->setupClasses();
        }
        $expectedSignature = rawurldecode($this->CheckClass->getRequestSignature());
        if( $actualSignature != $expectedSignature){
            JError::raiseNotice( 0,'The signature sent to Facebook differs from the one received.' );
             if (JDEBUG) JError::raiseNotice( 0,'Expected: '.$expectedSignature );
             if (JDEBUG) JError::raiseNotice( 0,'Actual: '.$actualSignature );   
            return;
        }
        if($code != '' ){
            if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__." code: ".$code );
            $this->params->set('auth_code', $code.'#_=_');
            if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__." param: ".$this->params->toString() );
            if(!is_object($this->CheckClass)){
                $this->setupClasses();
            }
            $this->CheckClass->storeParams($this->params, $this->config['pluginElement']);
            $this->inBackend = true;
            $this->displayMessage(JText::_($this->config['pluginLangPrefix'].'AUTHORIZED'), 'notice');
        }
    }
    
    private function prepareToPost($article){
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        $this->setupClasses();
        $articleObject = $this->getArticleObjectFromJoomlaArticle($article);
        $this->CheckClass->setArticleObject($articleObject);        
    }
 
    private function setupClasses() {
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        $folder = $this->config['classFolder'];
        $classNames = array(
            $this->config['fbookClass'],
            $this->config['jfbClass'],
            $this->config['shareControllerClass'],
            $this->config['fbControllerClass'],
            $this->config['articleClass']
        );
        $classFiles = array(
            $this->config['fbookClassFile'],
            $this->config['jfbClassFile'],
            $this->config['shareControllerFile'],
            $this->config['fbControllerFile'],
            $this->config['articleClassFile']
        );
        $classFolder = $this->config['classFolder'];
        for($i=0;$i<count($classNames);$i++){
            JLoader::register(
                $classNames[$i], 
                dirname(__FILE__).DS.$classFolder.DS.
                $classFiles[$i]
            );
        }
        $this->CheckClass = new $this->config['fbControllerClass']( 
            array(
                'fbAppID'               =>      $this->fbAppID,
                'fbAppSecret'           =>      $this->fbAppSecret,
                'fbOauthAccessToken'    =>      $this->fbOauthAccessToken,
                'fbOauthCode'           =>      $this->fbOauthCode,
                'fbPageID'              =>      $this->config['fbPageID'],
                'shareLogTableName'     =>      $this->config['shareLogTableName'],
                'pluginLangPrefix'      =>      $this->config['pluginLangPrefix'],
                'categoriesToShare'     =>      $this->config['categoriesToShare'],
                'shareDelay'            =>      $this->config['shareDelay'],
                'articlesNewerThan'     =>      $this->config['articlesNewerThan'],
                'inBackend'             =>      $this->inBackend
            )
        );
    }
    
    private function postArticleToFB() {
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        if( !$this->isInitialChecksOK() ) {
            $this->displayMessage(JText::_($this->CheckClass->error['message']) , $this->CheckClass->error['type']);
            return;
        }
        if ( $this->CheckClass->shareLinkToFB() ) {
            $this->displayMessage(JText::_($this->config['pluginLangPrefix'].'OK'));
            $token = $this->CheckClass->fbClass->getOauthAccessToken();
            $this->params->set('auth_code', '');
            $this->params->set('auth_token', $token);
            if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__." param: ".$this->params->toString() );
            if(!is_object($this->CheckClass)){
                $this->setupClasses();
            }
            $this->CheckClass->storeParams($this->params, $this->config['pluginElement']);
            return;
        }else if( ($this->CheckClass->fbClass->getErrorCode() == self::ERROR_OAUTH_EXCEPTION) && $this->CheckClass->fbClass->getOauthAccessToken() != "" ){
            $this->params->set('auth_code', '');
            $this->params->set('auth_token', '');
            if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__." reseted Tokens and Code " );
            if(!is_object($this->CheckClass)){
                $this->setupClasses();
            }
            $this->CheckClass->storeParams($this->params, $this->config['pluginElement']);
            $this->displayMessage(JText::_($this->config['pluginLangPrefix'].'OAUTHEXCEPT_RESETED'));
            return;
        }else{
            $this->displayMessage(JText::_($this->CheckClass->error['message']) , $this->CheckClass->error['type']);
            return;
        }
    }
    
    private function doInitialChecks() {
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        $this->CheckClass->isServerSupportingRequiredFunctions();
        $this->CheckClass->isServerSafeModeDisabled();
        $this->CheckClass->isFBAppDetailsEntered();
        $this->CheckClass->isArticleObjectIncluded();
        $this->CheckClass->isItemActive();
        $this->CheckClass->isItemPublished();
        $this->CheckClass->isItemNewEnough();
        $this->CheckClass->isItemPublic();
        $this->CheckClass->isCategoryToShare();
        $this->CheckClass->prepareTables();
        $this->CheckClass->isSharingToEarly();
        $this->CheckClass->isItemAlreadyShared();
        return $this->CheckClass->error;
    }

    public function isInitialChecksOK() {
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        $errorMessage = $this->doInitialChecks();
        if ( $errorMessage != FALSE ) {
            return FALSE;
        }
        return TRUE;
    }

    public function getArticleObjectFromJoomlaArticle($joomlaArticle) {
        if (JDEBUG) JError::raiseNotice( 0,__CLASS__."->".__FUNCTION__ );
        $articleObject = new stdClass();
        $articleObject->id = $joomlaArticle->id;
        $articleObject->language= (isset($joomlaArticle->language))? $joomlaArticle->language : '';
        $articleObject->link = $joomlaArticle->alias;
        $articleObject->full_url = $this->getFullURL($joomlaArticle->id);
        $articleObject->tags = $this->getArticleTagsArray($joomlaArticle->metakey);
        $articleObject->title = $joomlaArticle->title;
        $articleObject->catid = $joomlaArticle->catid;
        $articleObject->access = $joomlaArticle->access;
        $articleObject->publish_up = $joomlaArticle->publish_up;
        $articleObject->published = $joomlaArticle->state; 
        return $articleObject;
    }

    public function getFullURL($articleID) {
        $urlQuery = "?option=com_content&view=article&id=".$articleID;
        $fullURL = JURI::root()."index.php".$urlQuery;
        return $fullURL;
    }
    
    private function getArticleTagsArray($commaSpearatedMetaKeys) {
        if($commaSpearatedMetaKeys == ""){
            return;
        }
       $metaKeyArray = explode(",", $commaSpearatedMetaKeys);
       foreach ($metaKeyArray as $key => $value) {
           $tagsArray[] = trim(str_replace(" ", "", $value));
       }
       return $tagsArray;
    }

        private function insertOGTags($articleObj){
        if( $this->params->def('add_ogtags')==0 || !isset($articleObj->id) || $this->ogTagsAdded ){
            return;
        }
        $document = JFactory::getDocument();
        $metaDataArray = $this->getMetaDataArray($articleObj);
        foreach ($metaDataArray as $key => $value) {
            if($value !="") {
                $metaProp = '<meta property="'.$key.'" content="'.$value.'" />';
                $document->addCustomTag($metaProp);
            }
        }
        $this->ogTagsAdded = true;
    }

    private function getMetaDataArray($articleObj){
        $imageSrc = $this->getImageSrcFromContent($articleObj); 
        $imageSrc = ( isset($imageSrc) )? $imageSrc : "";
        $descNeedles = array("\n", "\r", "\"", "'");
        $desc = (isset($articleObj->introtext) )? strip_tags( str_replace($descNeedles, " ", $articleObj->introtext )) : "";
        $desc = (strlen($desc)>140) ? substr($desc, 0, 137)."..." : $desc;
        $joomlaConfig = JFactory::getConfig();
        $joomlaSiteName = $joomlaConfig->getValue( 'config.sitename' );
        $langObj = JFactory::getLanguage();
        $currentLang = str_replace( "-", "_", $langObj->getTag() );
        $metaData = array(
            'og:title'          =>  $articleObj->title,
            'og:image'          =>  $imageSrc,
            'og:description'    =>  $desc,
            'og:locale'         =>  $currentLang,
            'og:type'           =>  'website',
            'og:site_name'      =>  $joomlaSiteName,
            'og:url'            =>  $articleObj->getFullURL()
        );
        return $metaData;
    }

    private function getImageSrcFromContent($articleObj) {
        $content = ($articleObj->fulltext != "" )? $articleObj->fulltext : $articleObj->introtext;
        preg_match_all('/<img[^>]+>/i',$content, $imageNodes);

        $img = array();
        foreach( $imageNodes as $imgTag) {
            $pattern = "/src=[\"']?([^\"']?.*(png|jpg|gif))[\"']?/i";
            preg_match_all($pattern, $content, $img);
        }
        $firstImageSrc = "";
        if( !empty($img) ) {
            $imgArr = $img[1];
            $firstImageSrc = (isset($imgArr[0])) ? $this->getAbsUrl( $imgArr[0] ) : null;
        }
        return $firstImageSrc; 
    }

    private function getAbsUrl($url){
        if($url == "") return;
        $parsedURL = parse_url($url);
        $query = ( isset($parsedURL['query']) ) ? "?".$parsedURL['query'] : "" ;
        $path = $parsedURL['path'];
        if(strlen($parsedURL['path'])>2){
            $path = (substr_count($parsedURL['path'] , '/', 0, 1))? substr($parsedURL['path'], 1) : $parsedURL['path'];
        }
        $absURL = JURI::root().$path.$query;
        return $absURL;
    }
    
    public function displayMessage($msg, $messageType = "") {
        if(JDEBUG) JFactory::getApplication()->enqueueMessage( $msg, $messageType);
        $isSetToDisplayMessages = ($this->params->def('pingmessages')==0)?false:true;
        if( ! $isSetToDisplayMessages || ! $this->inBackend ){
            return;
        }
        if($messageType == 'notice'){
            $this->showNotice($msg);
            return;
        }else if($messageType == 'warning'){
            $this->showWarning($msg);
            return;
        }
        JFactory::getApplication()->enqueueMessage( $msg, $messageType);
    }
    
    public function showNotice($msg, $errorCode=0) {
        if(JDEBUG) JError::raiseNotice( $errorCode, $msg );
        $isSetToDisplayMessages = ($this->params->def('pingmessages')==0)?false:true;
        if( ! $isSetToDisplayMessages || ! $this->inBackend ){
            return;
        }else{
             JError::raiseNotice( $errorCode, $msg );
        }
    }
    
    public function showWarning($msg, $errorCode=0) {
        if(JDEBUG) JError::raiseWarning( $errorCode, $msg );
        $isSetToDisplayMessages = ($this->params->def('pingmessages')==0)?false:true;
        if( ! $isSetToDisplayMessages || ! $this->inBackend ){
            return;
        }else{
             JError::raiseWarning( $errorCode, $msg );
        }
    }
	
} // END CLASS

